/* 自定义消息类 */

#pragma once
#include <jsoncpp/json/json.h>
#include <string.h>
#include <memory>    //use for unique_ptr
#include <sstream>   //use for stringstream

#define TCP_DATA_MAX_LEN 1024
#define PORT 28989

/* 消息类型枚举 */
enum chat_msg_type
{
    Register = 0,          //0 注册请求
    Register_Resp,         //1 注册应答
    Login,                 //2 登录请求
    Login_Resp,            //3 登录应答
    AddFriend,             //4 添加好友请求
    AddFriend_Resp,        //5 添加好友请求应答
    SendMsg,               //6 发送消息
    SendMsg_Resp,          //7 发送消息应答
    PushMsg,               //8 推送消息
    PushMsg_Resp,          //9 推送消息应答
    PushAddFriendMsg,      //10 推送添加好友请求
    PushAddFriendMsg_Resp, //11 推送添加好友请求的应答 
    GetFriendMsg,          //12 获取全部好友信息
    GetFriendMsg_Resp,     //13 获取全部好友信息应答
    SetUserOffLine         //14
    //若后续需增加业务， 可在增加其他的消息类型
};

/* 应答状态枚举 */
enum reply_status
{
    REGISTER_SUCCESS = 0,  //0 注册成功
    REGISTER_FAILED,       //1 注册失败
    LOGIN_SUCCESS,         //2 登录成功
    LOGIN_FAILED,          //3 登陆失败
    ADDFRIEND_SUCCESS,     //4 添加好友成功
    ADDFRIEND_FAILED,      //5 添加好友失败
    SENDMSG_SUCCESS,       //6 发送消息成功
    SENDMSG_FAILED,        //7 发送给消息失败
    GETFRIEND_SUCCESS,     //8 获取好友列表成功
    GETFRIEND_FAILED       //9 获取好友列表失败
};

/* 封装的Json序列化&反序列化接口 */
class JsonUtil
{
public:
    static bool Serialize(const Json::Value& value, std::string* body)
    {
        Json::StreamWriterBuilder swb;
        std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());

        std::stringstream ss;
        int ret = sw->write(value, &ss);
        if (ret != 0) 
        {
            return false;
        }
        *body = ss.str();
        return true;
    }

    static bool UnSerialize(const std::string& body, Json::Value* value) 
    {
        Json::CharReaderBuilder crb;
        std::unique_ptr<Json::CharReader> cr(crb.newCharReader());

        std::string err;
        bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), value, &err);
        if (ret == false) 
        {
            return false;
        }
        return true;
    }
};


/*  
 *
 * 注册请求的消息格式
 *   sockfd_ (消息达到服务端之后， 由服务端接收之后， 打上sockfd_)
 *   msg_type_ : Register
 *   json_msg: {
 *      nickname : 'xxx'
 *      school : "xxx"
 *      telnum : "xxxx"
 *      passwd : "xxxx"
 *   }
 *
 * 注册的应答：
 *   msg_type_ : Register_Resp
 *   reply_status_ = REGISTER_SUCCESS / REGISTER_FAILED
 *      如果是REGISTER_SUCCESS : [user_id_]
 *
 *
 *
 * 登录的请求消息格式
 *   sockfd_ (消息达到服务端之后， 由服务端接收之后， 打上sockfd_)
 *   msg_type_ : Login
 *   json_msg_ : {
 *      telnum : xxx
 *      passwd : xxx
 *   }
 *
 *   登录的应答：
 *   msg_type : Login_Resp;
 *   reply_status_ : LOGIN_SUCCESS/LOGIN_FAILED
 *       如果是LOGIN_SUCCESS : [user_id_]
 *
 *
 *
 * 添加好友请求：
 *    msg_type_ : AddFriend
 *    json_msg_ :{
 *      fri_tel_num : xxxx
 *    }
 *
 *
 *  推送添加好友的请求
 *      msg_type : PushAddFriendMsg
 *      sockfd_ : 被添加方的套接字描述符
 *      json_msg_: {
 *          adder_nickname : xxx
 *          adder_school : xxx
 *          adder_userid : xxx
 *      }
 *
 * 推送添加好友的应答（被添加方发送给服务端的）
 *     msg_type : PushAddFriendMsg_Resp
 *     user_id : 被添加方的id
 *     reply_status : ADDFRIEND_SUCCESS / ADDFRIEND_FAILED
 *         如果说是ADDFRIEND_SUCCESS
 *             json_msg_ : 添加方的id
 *
 *  添加好友的应答：
 *      msg_type: AddFriend_Resp
 *      reply_status : ADDFRIEND_FAILED / ADDFRIEND_SUCCESS
 *          如果是成功：ADDFRIEND_SUCCESS
 *             json_msg_ : 
 *                 BeAdd_nickname : 被添加方的名字
 *                 BeAdd_school ： 被添加方的学校
 *                 BeAdd_userid : 被添加方的id
 * */

class ChatMsg
{
public:
    ChatMsg()
    {
        _sockfd = -1;
        _msg_type = -1;
        _user_id = -1;
        _reply_status = -1;
        _json_msg.clear();
    }

    /* 获取反序列化消息(for recv from client) */
    int GetChatMsg(int sockfd, const std::string& msg)
    {
        // 对网络数据进行Json反序列化
        Json::Value temp;
        bool ret = JsonUtil::UnSerialize(msg, &temp);
        if(ret == false)
        {
            return -1;
        }
        
        // 赋值
        _sockfd = sockfd;
        _msg_type = temp["msg_type"].asInt();
        _user_id = temp["user_id"].asInt();
        _reply_status = temp["reply_status"].asInt();
        _json_msg = temp["json_msg"];
        
        return 0;
    }

    /* 获取序列化消息(for send to client) */
    int GetStringMsg(std::string* msg)
    {
        Json::Value tmp;
        tmp["msg_type"] = _msg_type;
        tmp["user_id"] = _user_id;
        tmp["reply_status"] = _reply_status;
        tmp["json_msg"] = _json_msg;

        return JsonUtil::Serialize(tmp, msg);
    }

    /* 获取_json_msg的value */
    std::string GetValue(const std::string& key)
    {
        if(!_json_msg.isMember(key))
        {
            return "";
        }
        return _json_msg[key].asString();
    }

    /* 为_json_msg的value赋值 */
    void SetValue(const std::string& key, const std::string& value)
    {
        _json_msg[key] = value;
    }

    void SetValue(const std::string& key, int value)
    {
        _json_msg[key] = value;
    }
        
    /* 清空ChatMsg对象 */
    void Clear()
    {
        _msg_type = -1;
        _user_id = -1;
        _reply_status = -1;
        _json_msg.clear();
    }
    

public:
    int _sockfd;        //已连接的套接字描述符
    int _msg_type;      //消息类型（枚举）
    int _user_id;       //客户端用户id
    int _reply_status;  //应答确认状态

    /* Json消息
     *  内容随消息类型不同，字段也不同
     * */
    Json::Value _json_msg;
};
